library(SingleCellExperiment)
library(dplyr)
library(ggplot2)
library(nichenetr)
library(multinichenetr)
library(Seurat)

#We will look here at the top 50 predictions across all contrasts, senders, and receivers of interest.

prioritized_tbl_oi_all = get_top_n_lr_pairs(
  multinichenet_output$prioritization_tables, 
  top_n = 100, 
  rank_per_group = FALSE
  )
prioritized_tbl_oi = 
  multinichenet_output$prioritization_tables$group_prioritization_tbl %>%
  filter(id %in% prioritized_tbl_oi_all$id) %>%
  distinct(id, sender, receiver, ligand, receptor, group) %>% 
  left_join(prioritized_tbl_oi_all)
Joining with `by = join_by(id, sender, receiver, ligand, receptor, group)`
prioritized_tbl_oi$prioritization_score[is.na(prioritized_tbl_oi$prioritization_score)] = 0

senders_receivers = union(prioritized_tbl_oi$sender %>% unique(), prioritized_tbl_oi$receiver %>% unique()) %>% sort()

colors_sender = RColorBrewer::brewer.pal(n = length(senders_receivers), name = 'Spectral') %>% magrittr::set_names(senders_receivers)
colors_receiver = RColorBrewer::brewer.pal(n = length(senders_receivers), name = 'Spectral') %>% magrittr::set_names(senders_receivers)

circos_list = make_circos_group_comparison(prioritized_tbl_oi, colors_sender, colors_receiver)
Joining with `by = join_by(sender)`
Joining with `by = join_by(receiver)`
Joining with `by = join_by(sender)`
Joining with `by = join_by(receiver)`

#RColorBrewer::display.brewer.all()
gg
Error: object 'gg' not found
plot_oi
Warning: Removed 24 rows containing missing values or values outside the scale range (`geom_point()`).

group_oi = "end"
prioritized_tbl_oi_S_50 = prioritized_tbl_oi_all %>% 
  filter(group == group_oi) 
plot_oi = make_sample_lr_prod_activity_plots_Omnipath(
  multinichenet_output$prioritization_tables, 
  prioritized_tbl_oi_S_50 %>% inner_join(lr_network_all)
)
Joining with `by = join_by(ligand, receptor)`
Joining with `by = join_by(id)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(receiver, sender_receiver, lr_interaction, group, LR)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction)`
plot_oi
Warning: Removed 12 rows containing missing values or values outside the scale range (`geom_point()`).

group_oi = "ctl"
prioritized_tbl_oi_A_50 = prioritized_tbl_oi_all %>% 
  filter(group == group_oi) 
plot_oi = make_sample_lr_prod_activity_plots_Omnipath(
  multinichenet_output$prioritization_tables, 
  prioritized_tbl_oi_A_50 %>% inner_join(lr_network_all)
)
Joining with `by = join_by(ligand, receptor)`
Joining with `by = join_by(id)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(receiver, sender_receiver, lr_interaction, group, LR)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction)`
plot_oi

plot_oi = make_sample_lr_prod_activity_plots_Omnipath(
  multinichenet_output$prioritization_tables, 
  prioritized_tbl_oi_A_50 %>% inner_join(lr_network_all)
)
Joining with `by = join_by(ligand, receptor)`
Warning: There was 1 warning in `dplyr::filter()`.
ℹ In argument: `id %in% prioritized_tbl_oi$id`.
Caused by warning in `inner_join()`:
! Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 19 of `x` matches multiple rows in `y`.
ℹ Row 458 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship = "many-to-many"` to silence this warning.
Joining with `by = join_by(id)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(receiver, sender_receiver, lr_interaction, group, LR)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
plot_oi = make_sample_lr_prod_activity_plots_Omnipath(
  multinichenet_output$prioritization_tables, 
  prioritized_tbl_oi_A_50 %>% inner_join(lr_network_all)
)
Joining with `by = join_by(ligand, receptor)`
Warning: There was 1 warning in `dplyr::filter()`.
ℹ In argument: `id %in% prioritized_tbl_oi$id`.
Caused by warning in `inner_join()`:
! Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 19 of `x` matches multiple rows in `y`.
ℹ Row 458 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship = "many-to-many"` to silence this warning.
Joining with `by = join_by(id)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(receiver, sender_receiver, lr_interaction, group, LR)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
plot_oi
Warning: Removed 36 rows containing missing values or values outside the scale range (`geom_point()`).

# Typically, there are way more than 50 differentially expressed and active ligand-receptor pairs per group across all sender-receiver combinations. Therefore it might be useful to zoom in on specific cell types as senders/receivers:
# We will illustrate this for the "M_Monocyte_CD16" cell type as receiver in the M group:

group_oi = "int"

receivers_list = c("EC", "T", "Mph", "KCs", "MDMs", "Mono", "DCs", "HEP1.C", "Fib")

for (receiver_oi in receivers_list) {
  
  # Get the top 50 ligand-receptor pairs for the current receiver
  prioritized_tbl_oi = get_top_n_lr_pairs(
    multinichenet_output$prioritization_tables, 
    50, 
    groups_oi = group_oi, 
    receivers_oi = receiver_oi
  ) 
  
  
  plot_oi = make_sample_lr_prod_activity_plots_Omnipath(
    multinichenet_output$prioritization_tables, 
    prioritized_tbl_oi %>% inner_join(lr_network_all)
  )
  
  
  print(plot_oi)
  
  # Save the plot to a PDF file with the receiver's name
  file_name = paste0("multiniche_output/int_end/int_50top_", receiver_oi, "_receivers.pdf")
  ggsave(file_name, plot_oi, width = 10, height = 10, dpi = 300)
}
Joining with `by = join_by(ligand, receptor)`
Joining with `by = join_by(id)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(receiver, sender_receiver, lr_interaction, group, LR)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Warning: Removed 18 rows containing missing values or values outside the scale range (`geom_point()`).
Warning: Removed 18 rows containing missing values or values outside the scale range (`geom_point()`).
Joining with `by = join_by(ligand, receptor)`
Joining with `by = join_by(id)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(receiver, sender_receiver, lr_interaction, group, LR)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Warning: Removed 48 rows containing missing values or values outside the scale range (`geom_point()`).
Warning: Removed 48 rows containing missing values or values outside the scale range (`geom_point()`).
Joining with `by = join_by(ligand, receptor)`
Warning: There was 1 warning in `dplyr::filter()`.
ℹ In argument: `id %in% prioritized_tbl_oi$id`.
Caused by warning in `inner_join()`:
! Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 2 of `x` matches multiple rows in `y`.
ℹ Row 5422 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship = "many-to-many"` to silence this warning.
Joining with `by = join_by(id)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(receiver, sender_receiver, lr_interaction, group, LR)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Warning: Removed 48 rows containing missing values or values outside the scale range (`geom_point()`).
Warning: Removed 48 rows containing missing values or values outside the scale range (`geom_point()`).
Joining with `by = join_by(ligand, receptor)`
Warning: There was 1 warning in `dplyr::filter()`.
ℹ In argument: `id %in% prioritized_tbl_oi$id`.
Caused by warning in `inner_join()`:
! Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 6 of `x` matches multiple rows in `y`.
ℹ Row 458 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship = "many-to-many"` to silence this warning.
Joining with `by = join_by(id)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(receiver, sender_receiver, lr_interaction, group, LR)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Warning: Removed 69 rows containing missing values or values outside the scale range (`geom_point()`).
Warning: Removed 69 rows containing missing values or values outside the scale range (`geom_point()`).
Joining with `by = join_by(ligand, receptor)`
Warning: There was 1 warning in `dplyr::filter()`.
ℹ In argument: `id %in% prioritized_tbl_oi$id`.
Caused by warning in `inner_join()`:
! Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 11 of `x` matches multiple rows in `y`.
ℹ Row 5425 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship = "many-to-many"` to silence this warning.
Joining with `by = join_by(id)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(receiver, sender_receiver, lr_interaction, group, LR)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Warning: Removed 24 rows containing missing values or values outside the scale range (`geom_point()`).
Warning: Removed 24 rows containing missing values or values outside the scale range (`geom_point()`).
Joining with `by = join_by(ligand, receptor)`
Joining with `by = join_by(id)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(receiver, sender_receiver, lr_interaction, group, LR)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Warning: Removed 30 rows containing missing values or values outside the scale range (`geom_point()`).
Warning: Removed 30 rows containing missing values or values outside the scale range (`geom_point()`).
Joining with `by = join_by(ligand, receptor)`
Joining with `by = join_by(id)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(receiver, sender_receiver, lr_interaction, group, LR)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Warning: Removed 27 rows containing missing values or values outside the scale range (`geom_point()`).
Warning: Removed 27 rows containing missing values or values outside the scale range (`geom_point()`).
Joining with `by = join_by(ligand, receptor)`
Joining with `by = join_by(id)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(receiver, sender_receiver, lr_interaction, group, LR)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Warning: Removed 69 rows containing missing values or values outside the scale range (`geom_point()`).
Warning: Removed 69 rows containing missing values or values outside the scale range (`geom_point()`).
Joining with `by = join_by(ligand, receptor)`
Warning: There was 1 warning in `dplyr::filter()`.
ℹ In argument: `id %in% prioritized_tbl_oi$id`.
Caused by warning in `inner_join()`:
! Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 50 of `x` matches multiple rows in `y`.
ℹ Row 5869 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship = "many-to-many"` to silence this warning.
Joining with `by = join_by(id)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(receiver, sender_receiver, lr_interaction, group, LR)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Warning: Removed 36 rows containing missing values or values outside the scale range (`geom_point()`).
Warning: Removed 36 rows containing missing values or values outside the scale range (`geom_point()`).

for (senders_oi in cell_list) {
  
   # Get the top 50 ligand-receptor pairs for the current receiver
    prioritized_tbl_oi_M_50 = get_top_n_lr_pairs(
      multinichenet_output$prioritization_tables, 
      50, 
      groups_oi = group_oi, 
      senders_oi = senders_oi)
      plot_oi = make_sample_lr_prod_activity_plots_Omnipath(
      multinichenet_output$prioritization_tables, 
      prioritized_tbl_oi_M_50 %>% inner_join(lr_network_all))
  
  
    print(plot_oi)
    
  # Save the plot to a PDF file with the receiver's name
    file_name = paste0("multiniche_output/int_end/int_50top_", senders_oi, "_senders.pdf")
    ggsave(file_name, plot_oi, width = 10, height = 10, dpi = 300)
}
Joining with `by = join_by(ligand, receptor)`
Warning: There was 1 warning in `dplyr::filter()`.
ℹ In argument: `id %in% prioritized_tbl_oi$id`.
Caused by warning in `inner_join()`:
! Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 37 of `x` matches multiple rows in `y`.
ℹ Row 1902 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship = "many-to-many"` to silence this warning.
Joining with `by = join_by(id)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(receiver, sender_receiver, lr_interaction, group, LR)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Warning: Removed 27 rows containing missing values or values outside the scale range (`geom_point()`).
Warning: Removed 27 rows containing missing values or values outside the scale range (`geom_point()`).
Joining with `by = join_by(ligand, receptor)`
Warning: There was 1 warning in `dplyr::filter()`.
ℹ In argument: `id %in% prioritized_tbl_oi$id`.
Caused by warning in `inner_join()`:
! Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 3 of `x` matches multiple rows in `y`.
ℹ Row 5422 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship = "many-to-many"` to silence this warning.
Joining with `by = join_by(id)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(receiver, sender_receiver, lr_interaction, group, LR)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Warning: Removed 27 rows containing missing values or values outside the scale range (`geom_point()`).
Warning: Removed 27 rows containing missing values or values outside the scale range (`geom_point()`).
Joining with `by = join_by(ligand, receptor)`
Warning: There was 1 warning in `dplyr::filter()`.
ℹ In argument: `id %in% prioritized_tbl_oi$id`.
Caused by warning in `inner_join()`:
! Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 49 of `x` matches multiple rows in `y`.
ℹ Row 458 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship = "many-to-many"` to silence this warning.
Joining with `by = join_by(id)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(receiver, sender_receiver, lr_interaction, group, LR)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Warning: Removed 69 rows containing missing values or values outside the scale range (`geom_point()`).
Warning: Removed 69 rows containing missing values or values outside the scale range (`geom_point()`).
Joining with `by = join_by(ligand, receptor)`
Joining with `by = join_by(id)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(receiver, sender_receiver, lr_interaction, group, LR)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Warning: Removed 63 rows containing missing values or values outside the scale range (`geom_point()`).
Warning: Removed 63 rows containing missing values or values outside the scale range (`geom_point()`).
Joining with `by = join_by(ligand, receptor)`
Warning: There was 1 warning in `dplyr::filter()`.
ℹ In argument: `id %in% prioritized_tbl_oi$id`.
Caused by warning in `inner_join()`:
! Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 4 of `x` matches multiple rows in `y`.
ℹ Row 3048 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship = "many-to-many"` to silence this warning.
Joining with `by = join_by(id)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(receiver, sender_receiver, lr_interaction, group, LR)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Warning: Removed 30 rows containing missing values or values outside the scale range (`geom_point()`).
Warning: Removed 30 rows containing missing values or values outside the scale range (`geom_point()`).
Joining with `by = join_by(ligand, receptor)`
Warning: There was 1 warning in `dplyr::filter()`.
ℹ In argument: `id %in% prioritized_tbl_oi$id`.
Caused by warning in `inner_join()`:
! Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 4 of `x` matches multiple rows in `y`.
ℹ Row 5422 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship = "many-to-many"` to silence this warning.
Joining with `by = join_by(id)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(receiver, sender_receiver, lr_interaction, group, LR)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Warning: Removed 51 rows containing missing values or values outside the scale range (`geom_point()`).
Warning: Removed 51 rows containing missing values or values outside the scale range (`geom_point()`).
Joining with `by = join_by(ligand, receptor)`
Warning: There was 1 warning in `dplyr::filter()`.
ℹ In argument: `id %in% prioritized_tbl_oi$id`.
Caused by warning in `inner_join()`:
! Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 5 of `x` matches multiple rows in `y`.
ℹ Row 5422 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship = "many-to-many"` to silence this warning.
Joining with `by = join_by(id)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(receiver, sender_receiver, lr_interaction, group, LR)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Warning: Removed 39 rows containing missing values or values outside the scale range (`geom_point()`).
Warning: Removed 39 rows containing missing values or values outside the scale range (`geom_point()`).
Joining with `by = join_by(ligand, receptor)`
Joining with `by = join_by(id)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(receiver, sender_receiver, lr_interaction, group, LR)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Warning: Removed 33 rows containing missing values or values outside the scale range (`geom_point()`).
Warning: Removed 33 rows containing missing values or values outside the scale range (`geom_point()`).
Joining with `by = join_by(ligand, receptor)`
Warning: There was 1 warning in `dplyr::filter()`.
ℹ In argument: `id %in% prioritized_tbl_oi$id`.
Caused by warning in `inner_join()`:
! Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 11 of `x` matches multiple rows in `y`.
ℹ Row 5281 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship = "many-to-many"` to silence this warning.
Joining with `by = join_by(id)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(receiver, sender_receiver, lr_interaction, group, LR)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Warning: Removed 42 rows containing missing values or values outside the scale range (`geom_point()`).
Warning: Removed 42 rows containing missing values or values outside the scale range (`geom_point()`).

#Visualization of differential ligand-target links Without filtering of target genes based on LR-target expression correlation In another type of plot, we can visualize the ligand activities for a group-receiver combination, and show the predicted ligand-target links, and also the expression of the predicted target genes across samples.

For this, we now need to define a receiver cell type of interest. As example, we will take CLEC9A cells as receiver, and look at the top 10 sender Ligand-receiverReceptor pairs with these cells as receiver.

  # Display the first part of the combined plot (optional)
  print(combined_plot)
$combined_plot

$legends

In case we are interested in specific ligand and want to find the downstream genes

group_oi = "int"
receiver_oi = "EC"
ligands_oi = "Tgfb1" # add here the ligand
prioritized_tbl_ligands_oi = get_top_n_lr_pairs(
  multinichenet_output$prioritization_tables, 
  10000, 
  groups_oi = group_oi, 
  receivers_oi = receiver_oi
  ) %>% filter(ligand %in% ligands_oi) # ligands should still be in the output tables of course

prioritized_tbl_ligands_oi

combined_plot = make_ligand_activity_target_plot(
  group_oi, 
  receiver_oi, 
  prioritized_tbl_ligands_oi, 
  multinichenet_output$prioritization_tables, 
  multinichenet_output$ligand_activities_targets_DEgenes, 
  contrast_tbl, 
  multinichenet_output$grouping_tbl, 
  multinichenet_output$celltype_info, 
  ligand_target_matrix, 
  plot_legend = FALSE)
Joining with `by = join_by(contrast)`
Error in dimnames(x) <- dn : 
  length of 'dimnames' [1] not equal to array extent

With filtering of target genes based on LR-target expression correlation

In the previous plots, target genes were shown that are predicted as target gene of ligands based on prior knowledge. However, we can use the multi-sample nature of this data to filter target genes based on expression correlation between the upstream ligand-receptor pair and the downstream target gene. We will filter out correlated ligand-receptor –> target links that both show high expression correlation (spearman or pearson correlation > 0.50 in this example) and have some prior knowledge to support their link. Note that you can only make these visualization if you ran step 7 of the core MultiNicheNet analysis.

group_oi = "end"
for (receiver_oi in cell_list) {
  
  # Filter and prepare the data
  lr_target_prior_cor_filtered = multinichenet_output$lr_target_prior_cor %>%
    inner_join(
      multinichenet_output$ligand_activities_targets_DEgenes$ligand_activities %>% 
        distinct(ligand, target, direction_regulation, contrast)
    ) %>% 
    inner_join(contrast_tbl) %>% filter(group == group_oi, receiver == receiver_oi)
  
  lr_target_prior_cor_filtered_up = lr_target_prior_cor_filtered %>% 
    filter(direction_regulation == "up") %>% 
    filter((rank_of_target < top_n_target) & (pearson > 0.50 | spearman > 0.50))
  
  lr_target_prior_cor_filtered_down = lr_target_prior_cor_filtered %>% 
    filter(direction_regulation == "down") %>% 
    filter((rank_of_target < top_n_target) & (pearson < -0.50 | spearman < -0.50)) # downregulation -- negative correlation
  
  lr_target_prior_cor_filtered = bind_rows(
    lr_target_prior_cor_filtered_up, 
    lr_target_prior_cor_filtered_down)
  
  # Get the top 50 ligand-receptor pairs for the current receiver
  prioritized_tbl_oi = get_top_n_lr_pairs(
    multinichenet_output$prioritization_tables, 
    50, 
    groups_oi = group_oi, 
    receivers_oi = receiver_oi)
  #Now we will visualize the top correlated target genes for the LR pairs that are also in the top 50 LR pairs discriminating the groups from each other
  # Create the correlation plot
  lr_target_correlation_plot = make_lr_target_correlation_plot(
    multinichenet_output$prioritization_tables, 
    prioritized_tbl_oi,  
    lr_target_prior_cor_filtered, 
    multinichenet_output$grouping_tbl, 
    multinichenet_output$celltype_info, 
    receiver_oi,
    plot_legend = FALSE)
  
  # Display the combined plot (optional)
  print(lr_target_correlation_plot$combined_plot)
  
  # Save the plot to a PDF file with the receiver's name
  file_name = paste0("multiniche_output/int_end/correlationplot/", receiver_oi, "_end_ligand_target_correlation.pdf")
  ggsave(file_name, lr_target_correlation_plot$combined_plot, width = 19, height = 13, dpi = 300)
}
Joining with `by = join_by(receiver, ligand, target)`
Warning in inner_join(., multinichenet_output$ligand_activities_targets_DEgenes$ligand_activities %>%  :
  Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 20 of `x` matches multiple rows in `y`.
ℹ Row 321004 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship = "many-to-many"` to silence this warning.
Joining with `by = join_by(contrast)`
Joining with `by = join_by(gene)`
Joining with `by = join_by(receiver, ligand, target)`
Warning in inner_join(., multinichenet_output$ligand_activities_targets_DEgenes$ligand_activities %>%  :
  Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 20 of `x` matches multiple rows in `y`.
ℹ Row 321004 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship = "many-to-many"` to silence this warning.
Joining with `by = join_by(contrast)`
Joining with `by = join_by(gene)`
Joining with `by = join_by(receiver, ligand, target)`
Warning in inner_join(., multinichenet_output$ligand_activities_targets_DEgenes$ligand_activities %>%  :
  Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 20 of `x` matches multiple rows in `y`.
ℹ Row 321004 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship = "many-to-many"` to silence this warning.
Joining with `by = join_by(contrast)`
Joining with `by = join_by(gene)`
Joining with `by = join_by(receiver, ligand, target)`
Warning in inner_join(., multinichenet_output$ligand_activities_targets_DEgenes$ligand_activities %>%  :
  Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 20 of `x` matches multiple rows in `y`.
ℹ Row 321004 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship = "many-to-many"` to silence this warning.
Joining with `by = join_by(contrast)`
Joining with `by = join_by(gene)`
Joining with `by = join_by(receiver, ligand, target)`
Warning in inner_join(., multinichenet_output$ligand_activities_targets_DEgenes$ligand_activities %>%  :
  Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 20 of `x` matches multiple rows in `y`.
ℹ Row 321004 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship = "many-to-many"` to silence this warning.
Joining with `by = join_by(contrast)`
Joining with `by = join_by(gene)`
Joining with `by = join_by(receiver, ligand, target)`
Warning in inner_join(., multinichenet_output$ligand_activities_targets_DEgenes$ligand_activities %>%  :
  Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 20 of `x` matches multiple rows in `y`.
ℹ Row 321004 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship = "many-to-many"` to silence this warning.
Joining with `by = join_by(contrast)`
Joining with `by = join_by(gene)`
Joining with `by = join_by(receiver, ligand, target)`
Warning in inner_join(., multinichenet_output$ligand_activities_targets_DEgenes$ligand_activities %>%  :
  Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 20 of `x` matches multiple rows in `y`.
ℹ Row 321004 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship = "many-to-many"` to silence this warning.
Joining with `by = join_by(contrast)`
Joining with `by = join_by(gene)`
Joining with `by = join_by(receiver, ligand, target)`
Warning in inner_join(., multinichenet_output$ligand_activities_targets_DEgenes$ligand_activities %>%  :
  Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 20 of `x` matches multiple rows in `y`.
ℹ Row 321004 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship = "many-to-many"` to silence this warning.
Joining with `by = join_by(contrast)`
Joining with `by = join_by(gene)`
Joining with `by = join_by(receiver, ligand, target)`
Warning in inner_join(., multinichenet_output$ligand_activities_targets_DEgenes$ligand_activities %>%  :
  Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 20 of `x` matches multiple rows in `y`.
ℹ Row 321004 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship = "many-to-many"` to silence this warning.
Joining with `by = join_by(contrast)`
Joining with `by = join_by(gene)`

visualize the expression correlation in the following way for a selected LR pair and their targets:

ligand_oi = "Tgfb1"
receptor_oi = "Tgfbr3"
sender_oi = c("Mono","Mph")
receiver_oi = "EC"

lr_target_scatter_plot = make_lr_target_scatter_plot(
  multinichenet_output$prioritization_tables, 
  ligand_oi, receptor_oi, sender_oi, receiver_oi, 
  multinichenet_output$celltype_info, 
  multinichenet_output$grouping_tbl, 
  lr_target_prior_cor_filtered)
Joining with `by = join_by(sample)`
Warning: There was 1 warning in `dplyr::filter()`.
ℹ In argument: `sender == sender_oi`.
Caused by warning in `sender == sender_oi`:
! longer object length is not a multiple of shorter object length
lr_target_scatter_plot
`geom_smooth()` using formula = 'y ~ x'

Next chapt ,Intercellular regulatory network inference and visualization

In the plots before, we demonstrated that some DE genes have both expression correlation and prior knowledge support to be downstream of ligand-receptor pairs. Interestingly, some target genes can be ligands or receptors themselves. This illustrates that cells can send signals to other cells, who as a response to these signals produce signals themselves to feedback to the original sender cells, or who will effect other cell types.

As last plot, we can generate a ‘systems’ view of these intercellular feedback and cascade processes than can be occuring between the different cell populations involved. In this plot, we will draw links between ligands of sender cell types their ligand/receptor-annotated target genes in receiver cell types. So links are ###ligand-target links (= gene regulatory links) and not ligand-receptor protein-protein interactions#####! We will infer this intercellular regulatory network here for the top50 interactions. You can increase this to include more hits of course (recommended).

prioritized_tbl_oi = get_top_n_lr_pairs(
  multinichenet_output$prioritization_tables, 
  150, 
  rank_per_group = FALSE)

lr_target_prior_cor_filtered = 
  multinichenet_output$prioritization_tables$group_prioritization_tbl$group %>% unique() %>% 
  lapply(function(group_oi){
    lr_target_prior_cor_filtered = multinichenet_output$lr_target_prior_cor %>%
      inner_join(
        multinichenet_output$ligand_activities_targets_DEgenes$ligand_activities %>%
          distinct(ligand, target, direction_regulation, contrast)
        ) %>% 
      inner_join(contrast_tbl) %>% filter(group == group_oi)
    
    lr_target_prior_cor_filtered_up = lr_target_prior_cor_filtered %>% 
      filter(direction_regulation == "up") %>% 
      filter( (rank_of_target < top_n_target) & (pearson > 0.50 | spearman > 0.50))
    
    lr_target_prior_cor_filtered_down = lr_target_prior_cor_filtered %>% 
      filter(direction_regulation == "down") %>% 
      filter( (rank_of_target < top_n_target) & (pearson < -0.50 | spearman < -0.50))
    lr_target_prior_cor_filtered = bind_rows(
      lr_target_prior_cor_filtered_up, 
      lr_target_prior_cor_filtered_down
      )
}) %>% bind_rows()
Joining with `by = join_by(receiver, ligand, target)`
Warning in inner_join(., multinichenet_output$ligand_activities_targets_DEgenes$ligand_activities %>%  :
  Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 87 of `x` matches multiple rows in `y`.
ℹ Row 1654999 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship = "many-to-many"` to silence this warning.
Joining with `by = join_by(contrast)`
Joining with `by = join_by(receiver, ligand, target)`
Warning in inner_join(., multinichenet_output$ligand_activities_targets_DEgenes$ligand_activities %>%  :
  Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 87 of `x` matches multiple rows in `y`.
ℹ Row 1654999 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship = "many-to-many"` to silence this warning.
Joining with `by = join_by(contrast)`
Joining with `by = join_by(receiver, ligand, target)`
Warning in inner_join(., multinichenet_output$ligand_activities_targets_DEgenes$ligand_activities %>%  :
  Detected an unexpected many-to-many relationship between `x` and `y`.
ℹ Row 87 of `x` matches multiple rows in `y`.
ℹ Row 1654999 of `y` matches multiple rows in `x`.
ℹ If a many-to-many relationship is expected, set `relationship = "many-to-many"` to silence this warning.
Joining with `by = join_by(contrast)`
lr_target_df = lr_target_prior_cor_filtered %>% 
  distinct(group, sender, receiver, ligand, receptor, id, target, direction_regulation) 
network = infer_intercellular_regulatory_network(lr_target_df, prioritized_tbl_oi)
network$links %>% head()
network_graph = visualize_network(network, colors_sender)
network_graph$plot

ggsave("multiniche_output/multicontrast/output/intercellular_regulatory_network.pdf", network_graph$plot, width = 18, height = 13,dpi = 300)

Interestingly, we can also use this network to further prioritize differential CCC interactions. Here we will assume that the most important LR interactions are the ones that are involved in this intercellular regulatory network. We can get these interactions as follows:

prioritized_tbl_oi_network = prioritized_tbl_oi %>% inner_join(
  network$prioritized_lr_interactions)
Joining with `by = join_by(group, sender, receiver, ligand, receptor)`
prioritized_tbl_oi_network

Interestingly, we can also use this network to further prioritize differential CCC interactions. Here we will assume that the most important LR interactions are the ones that are involved in this intercellular regulatory network. We can get these interactions as follows:

group_oi = "end"
prioritized_tbl_oi_Int = prioritized_tbl_oi_network %>% filter(group == group_oi)

plot_oi = make_sample_lr_prod_activity_plots_Omnipath(
  multinichenet_output$prioritization_tables, 
  prioritized_tbl_oi_Int %>% inner_join(lr_network_all)
  )
Joining with `by = join_by(ligand, receptor)`
Joining with `by = join_by(id)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction, group)`
Joining with `by = join_by(receiver, sender_receiver, lr_interaction, group, LR)`
Joining with `by = join_by(id, sender, receiver, sender_receiver, lr_interaction)`
plot_oi
Warning: Removed 21 rows containing missing values or values outside the scale range (`geom_point()`).
ggsave("multiniche_output/int_end/int_Prioritized_LR_based_on_intrecellular_network.pdf", plot_oi, width = 14, height = 8,dpi = 300)
Warning: Removed 21 rows containing missing values or values outside the scale range (`geom_point()`).

LS0tDQp0aXRsZTogIk11bHRpbmljaGVuZXQgb3V0cHV0IGFuYWx5c2lzIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KDQpgYGB7cn0NCmxpYnJhcnkoU2luZ2xlQ2VsbEV4cGVyaW1lbnQpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShnZ3Bsb3QyKQ0KbGlicmFyeShuaWNoZW5ldHIpDQpsaWJyYXJ5KG11bHRpbmljaGVuZXRyKQ0KbGlicmFyeShTZXVyYXQpDQpgYGANCg0KI1dlIHdpbGwgbG9vayBoZXJlIGF0IHRoZSB0b3AgNTAgcHJlZGljdGlvbnMgYWNyb3NzIGFsbCBjb250cmFzdHMsIHNlbmRlcnMsIGFuZCByZWNlaXZlcnMgb2YgaW50ZXJlc3QuDQpgYGB7cn0NCnByaW9yaXRpemVkX3RibF9vaV9hbGwgPSBnZXRfdG9wX25fbHJfcGFpcnMoDQogIG11bHRpbmljaGVuZXRfb3V0cHV0JHByaW9yaXRpemF0aW9uX3RhYmxlcywgDQogIHRvcF9uID0gNTAsIA0KICByYW5rX3Blcl9ncm91cCA9IEZBTFNFDQogICkNCmBgYA0KDQpgYGB7cn0NCnByaW9yaXRpemVkX3RibF9vaSA9IA0KICBtdWx0aW5pY2hlbmV0X291dHB1dCRwcmlvcml0aXphdGlvbl90YWJsZXMkZ3JvdXBfcHJpb3JpdGl6YXRpb25fdGJsICU+JQ0KICBmaWx0ZXIoaWQgJWluJSBwcmlvcml0aXplZF90Ymxfb2lfYWxsJGlkKSAlPiUNCiAgZGlzdGluY3QoaWQsIHNlbmRlciwgcmVjZWl2ZXIsIGxpZ2FuZCwgcmVjZXB0b3IsIGdyb3VwKSAlPiUgDQogIGxlZnRfam9pbihwcmlvcml0aXplZF90Ymxfb2lfYWxsKQ0KcHJpb3JpdGl6ZWRfdGJsX29pJHByaW9yaXRpemF0aW9uX3Njb3JlW2lzLm5hKHByaW9yaXRpemVkX3RibF9vaSRwcmlvcml0aXphdGlvbl9zY29yZSldID0gMA0KDQpzZW5kZXJzX3JlY2VpdmVycyA9IHVuaW9uKHByaW9yaXRpemVkX3RibF9vaSRzZW5kZXIgJT4lIHVuaXF1ZSgpLCBwcmlvcml0aXplZF90Ymxfb2kkcmVjZWl2ZXIgJT4lIHVuaXF1ZSgpKSAlPiUgc29ydCgpDQoNCmNvbG9yc19zZW5kZXIgPSBSQ29sb3JCcmV3ZXI6OmJyZXdlci5wYWwobiA9IGxlbmd0aChzZW5kZXJzX3JlY2VpdmVycyksIG5hbWUgPSAnU3BlY3RyYWwnKSAlPiUgbWFncml0dHI6OnNldF9uYW1lcyhzZW5kZXJzX3JlY2VpdmVycykNCmNvbG9yc19yZWNlaXZlciA9IFJDb2xvckJyZXdlcjo6YnJld2VyLnBhbChuID0gbGVuZ3RoKHNlbmRlcnNfcmVjZWl2ZXJzKSwgbmFtZSA9ICdTcGVjdHJhbCcpICU+JSBtYWdyaXR0cjo6c2V0X25hbWVzKHNlbmRlcnNfcmVjZWl2ZXJzKQ0KDQpjaXJjb3NfbGlzdCA9IG1ha2VfY2lyY29zX2dyb3VwX2NvbXBhcmlzb24ocHJpb3JpdGl6ZWRfdGJsX29pLCBjb2xvcnNfc2VuZGVyLCBjb2xvcnNfcmVjZWl2ZXIpDQoNCiNSQ29sb3JCcmV3ZXI6OmRpc3BsYXkuYnJld2VyLmFsbCgpDQpgYGANCmBgYHtyfQ0KRGltUGxvdChTY19maWx0ZXJlZCwgZ3JvdXAuYnkgPSAiY29uZGl0aW9uIixzaHVmZmxlID0gVCkNCg0KZ3JvdXBfb2kgPSAiZW5kIiAjIHB1dCBncm91cCBvZiBpbnRlcmVzdCBoZXJlLCBlLmcuICJjdGwiDQpwcmlvcml0aXplZF90Ymxfb2lfTV81MCA9IHByaW9yaXRpemVkX3RibF9vaV9hbGwgJT4lIA0KICBmaWx0ZXIoZ3JvdXAgPT0gZ3JvdXBfb2kpDQpwbG90X29pID0gbWFrZV9zYW1wbGVfbHJfcHJvZF9hY3Rpdml0eV9wbG90c19PbW5pcGF0aCgNCiAgbXVsdGluaWNoZW5ldF9vdXRwdXQkcHJpb3JpdGl6YXRpb25fdGFibGVzLCANCiAgcHJpb3JpdGl6ZWRfdGJsX29pX01fNTAgJT4lIGlubmVyX2pvaW4obHJfbmV0d29ya19hbGwpDQogICkNCnBsb3Rfb2kNCg0KZ2dzYXZlKCJtdWx0aW5pY2hlX291dHB1dC9pbnRfZW5kL2ludF81MHRvcC5wZGYiLCBwbG90X29pLCB3aWR0aCA9IDEwLCBoZWlnaHQgPSAxMCxkcGkgPSAzMDApDQpgYGANCg0KYGBge3J9DQpncm91cF9vaSA9ICJlbmQiDQpwcmlvcml0aXplZF90Ymxfb2lfU181MCA9IHByaW9yaXRpemVkX3RibF9vaV9hbGwgJT4lIA0KICBmaWx0ZXIoZ3JvdXAgPT0gZ3JvdXBfb2kpIA0KcGxvdF9vaSA9IG1ha2Vfc2FtcGxlX2xyX3Byb2RfYWN0aXZpdHlfcGxvdHNfT21uaXBhdGgoDQogIG11bHRpbmljaGVuZXRfb3V0cHV0JHByaW9yaXRpemF0aW9uX3RhYmxlcywgDQogIHByaW9yaXRpemVkX3RibF9vaV9TXzUwICU+JSBpbm5lcl9qb2luKGxyX25ldHdvcmtfYWxsKQ0KKQ0KcGxvdF9vaQ0KYGBgDQoNCmBgYHtyfQ0KZ3JvdXBfb2kgPSAiY3RsIg0KcHJpb3JpdGl6ZWRfdGJsX29pX0FfNTAgPSBwcmlvcml0aXplZF90Ymxfb2lfYWxsICU+JSANCiAgZmlsdGVyKGdyb3VwID09IGdyb3VwX29pKSANCnBsb3Rfb2kgPSBtYWtlX3NhbXBsZV9scl9wcm9kX2FjdGl2aXR5X3Bsb3RzX09tbmlwYXRoKA0KICBtdWx0aW5pY2hlbmV0X291dHB1dCRwcmlvcml0aXphdGlvbl90YWJsZXMsIA0KICBwcmlvcml0aXplZF90Ymxfb2lfQV81MCAlPiUgaW5uZXJfam9pbihscl9uZXR3b3JrX2FsbCkNCikNCnBsb3Rfb2kNCmBgYA0KDQpgYGB7cn0NCiMgQXMgeW91IGNvdWxkIG9ic2VydmUgZnJvbSB0aGUgQ2lyY29zIENob3JkRGlhZ3JhbSBhbmQgSW50ZXJwcmV0YWJsZSBCdWJibGUgcGxvdHMgYWJvdmU6IHdlIGZpbmQgbW9yZSBzcGVjaWZpYyBpbnRlcmFjdGlvbnMgZm9yIHRoZSBvbmUtZ3JvdXAgdGhhbiBmb3IgdGhlIG90aGVyLiBJZiB5b3Ugd2FudCB0byB2aXN1YWxpemUgbW9yZSBpbnRlcmFjdGlvbnMgc3BlY2lmaWMgZm9yIGEgZ3JvdXAgb2YgaW50ZXJlc3QsIHNvIG5vdCByZXN0cmljdGVkIHRvIGUuZy4gdGhlIHRvcDUwIG92ZXJhbGwsIGJ1dCB0aGUgdG9wNTAgZm9yIGEgZ3JvdXAgb2YgaW50ZXJlc3QsIHlvdSBjYW4gcnVuIHRoZSBmb2xsb3dpbmc6DQoNCmdyb3VwX29pID0gImludCINCnByaW9yaXRpemVkX3RibF9vaV9BXzUwID0gZ2V0X3RvcF9uX2xyX3BhaXJzKA0KICBtdWx0aW5pY2hlbmV0X291dHB1dCRwcmlvcml0aXphdGlvbl90YWJsZXMsIA0KICA1MCwgDQogIGdyb3Vwc19vaSA9IGdyb3VwX29pKSANCnBsb3Rfb2kgPSBtYWtlX3NhbXBsZV9scl9wcm9kX2FjdGl2aXR5X3Bsb3RzX09tbmlwYXRoKA0KICBtdWx0aW5pY2hlbmV0X291dHB1dCRwcmlvcml0aXphdGlvbl90YWJsZXMsIA0KICBwcmlvcml0aXplZF90Ymxfb2lfQV81MCAlPiUgaW5uZXJfam9pbihscl9uZXR3b3JrX2FsbCkNCikNCnBsb3Rfb2kNCg0KZ2dzYXZlKCJtdWx0aW5pY2hlX291dHB1dC9pbnRfZW5kL2ludF81MHRvcF9ncm91cF9pbnRlcmVzdC5wZGYiLCBwbG90X29pLCB3aWR0aCA9IDEwLCBoZWlnaHQgPSAxMCxkcGkgPSAzMDApDQpgYGANCg0KYGBge3J9DQojIFR5cGljYWxseSwgdGhlcmUgYXJlIHdheSBtb3JlIHRoYW4gNTAgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGFuZCBhY3RpdmUgbGlnYW5kLXJlY2VwdG9yIHBhaXJzIHBlciBncm91cCBhY3Jvc3MgYWxsIHNlbmRlci1yZWNlaXZlciBjb21iaW5hdGlvbnMuIFRoZXJlZm9yZSBpdCBtaWdodCBiZSB1c2VmdWwgdG8gem9vbSBpbiBvbiBzcGVjaWZpYyBjZWxsIHR5cGVzIGFzIHNlbmRlcnMvcmVjZWl2ZXJzOg0KIyBXZSB3aWxsIGlsbHVzdHJhdGUgdGhpcyBmb3IgdGhlICJNX01vbm9jeXRlX0NEMTYiIGNlbGwgdHlwZSBhcyByZWNlaXZlciBpbiB0aGUgTSBncm91cDoNCg0KZ3JvdXBfb2kgPSAiaW50Ig0KDQpjZWxsX2xpc3QgPSBjKCJFQyIsICJUIiwgIk1waCIsICJLQ3MiLCAiTURNcyIsICJNb25vIiwgIkRDcyIsICJIRVAxLkMiLCAiRmliIikgIyMgYWRkIHRoZSBjZWxscyB3ZSBkaWQgdGhlIGFuYWx5c2lzIHdpdGggKGNlbGxzX3RvX2tlZXApDQoNCmZvciAocmVjZWl2ZXJfb2kgaW4gY2VsbF9saXN0KSB7DQogIA0KICAjIEdldCB0aGUgdG9wIDUwIGxpZ2FuZC1yZWNlcHRvciBwYWlycyBmb3IgdGhlIGN1cnJlbnQgcmVjZWl2ZXINCiAgcHJpb3JpdGl6ZWRfdGJsX29pID0gZ2V0X3RvcF9uX2xyX3BhaXJzKA0KICAgIG11bHRpbmljaGVuZXRfb3V0cHV0JHByaW9yaXRpemF0aW9uX3RhYmxlcywgDQogICAgNTAsIA0KICAgIGdyb3Vwc19vaSA9IGdyb3VwX29pLCANCiAgICByZWNlaXZlcnNfb2kgPSByZWNlaXZlcl9vaQ0KICApIA0KICANCiAgDQogIHBsb3Rfb2kgPSBtYWtlX3NhbXBsZV9scl9wcm9kX2FjdGl2aXR5X3Bsb3RzX09tbmlwYXRoKA0KICAgIG11bHRpbmljaGVuZXRfb3V0cHV0JHByaW9yaXRpemF0aW9uX3RhYmxlcywgDQogICAgcHJpb3JpdGl6ZWRfdGJsX29pICU+JSBpbm5lcl9qb2luKGxyX25ldHdvcmtfYWxsKQ0KICApDQogIA0KICANCiAgcHJpbnQocGxvdF9vaSkNCiAgDQogICMgU2F2ZSB0aGUgcGxvdCB0byBhIFBERiBmaWxlIHdpdGggdGhlIHJlY2VpdmVyJ3MgbmFtZQ0KICBmaWxlX25hbWUgPSBwYXN0ZTAoIm11bHRpbmljaGVfb3V0cHV0L2ludF9lbmQvaW50XzUwdG9wXyIsIHJlY2VpdmVyX29pLCAiX3JlY2VpdmVycy5wZGYiKQ0KICBnZ3NhdmUoZmlsZV9uYW1lLCBwbG90X29pLCB3aWR0aCA9IDEwLCBoZWlnaHQgPSAxMCwgZHBpID0gMzAwKQ0KfQ0KYGBgDQoNCmBgYHtyfQ0KIyBBbmQgbm93IGFzIHNlbmRlcjoNCg0KZm9yIChzZW5kZXJzX29pIGluIGNlbGxfbGlzdCkgew0KICANCiAgICMgR2V0IHRoZSB0b3AgNTAgbGlnYW5kLXJlY2VwdG9yIHBhaXJzIGZvciB0aGUgY3VycmVudCByZWNlaXZlcg0KICAgIHByaW9yaXRpemVkX3RibF9vaV9NXzUwID0gZ2V0X3RvcF9uX2xyX3BhaXJzKA0KICAgICAgbXVsdGluaWNoZW5ldF9vdXRwdXQkcHJpb3JpdGl6YXRpb25fdGFibGVzLCANCiAgICAgIDUwLCANCiAgICAgIGdyb3Vwc19vaSA9IGdyb3VwX29pLCANCiAgICAgIHNlbmRlcnNfb2kgPSBzZW5kZXJzX29pKQ0KICAgICAgcGxvdF9vaSA9IG1ha2Vfc2FtcGxlX2xyX3Byb2RfYWN0aXZpdHlfcGxvdHNfT21uaXBhdGgoDQogICAgICBtdWx0aW5pY2hlbmV0X291dHB1dCRwcmlvcml0aXphdGlvbl90YWJsZXMsIA0KICAgICAgcHJpb3JpdGl6ZWRfdGJsX29pX01fNTAgJT4lIGlubmVyX2pvaW4obHJfbmV0d29ya19hbGwpKQ0KICANCiAgDQogICAgcHJpbnQocGxvdF9vaSkNCiAgICANCiAgIyBTYXZlIHRoZSBwbG90IHRvIGEgUERGIGZpbGUgd2l0aCB0aGUgcmVjZWl2ZXIncyBuYW1lDQogICAgZmlsZV9uYW1lID0gcGFzdGUwKCJtdWx0aW5pY2hlX291dHB1dC9pbnRfZW5kL2ludF81MHRvcF8iLCBzZW5kZXJzX29pLCAiX3NlbmRlcnMucGRmIikNCiAgICBnZ3NhdmUoZmlsZV9uYW1lLCBwbG90X29pLCB3aWR0aCA9IDEwLCBoZWlnaHQgPSAxMCwgZHBpID0gMzAwKQ0KfQ0KYGBgDQojVmlzdWFsaXphdGlvbiBvZiBkaWZmZXJlbnRpYWwgbGlnYW5kLXRhcmdldCBsaW5rcw0KV2l0aG91dCBmaWx0ZXJpbmcgb2YgdGFyZ2V0IGdlbmVzIGJhc2VkIG9uIExSLXRhcmdldCBleHByZXNzaW9uIGNvcnJlbGF0aW9uDQpJbiBhbm90aGVyIHR5cGUgb2YgcGxvdCwgd2UgY2FuIHZpc3VhbGl6ZSB0aGUgbGlnYW5kIGFjdGl2aXRpZXMgZm9yIGEgZ3JvdXAtcmVjZWl2ZXIgY29tYmluYXRpb24sIGFuZCBzaG93IHRoZSBwcmVkaWN0ZWQgbGlnYW5kLXRhcmdldCBsaW5rcywgYW5kIGFsc28gdGhlIGV4cHJlc3Npb24gb2YgdGhlIHByZWRpY3RlZCB0YXJnZXQgZ2VuZXMgYWNyb3NzIHNhbXBsZXMuDQoNCkZvciB0aGlzLCB3ZSBub3cgbmVlZCB0byBkZWZpbmUgYSByZWNlaXZlciBjZWxsIHR5cGUgb2YgaW50ZXJlc3QuIEFzIGV4YW1wbGUsIHdlIHdpbGwgdGFrZSBDTEVDOUEgY2VsbHMgYXMgcmVjZWl2ZXIsIGFuZCBsb29rIGF0IHRoZSB0b3AgMTAgc2VuZGVyIExpZ2FuZC1yZWNlaXZlclJlY2VwdG9yIHBhaXJzIHdpdGggdGhlc2UgY2VsbHMgYXMgcmVjZWl2ZXIuDQoNCmBgYHtyfQ0KDQpmb3IgKHJlY2VpdmVyX29pIGluIGNlbGxfbGlzdCkgew0KICANCiAgIyBHZXQgdGhlIHRvcCAxMCBsaWdhbmQtcmVjZXB0b3IgcGFpcnMgZm9yIHRoZSBjdXJyZW50IHJlY2VpdmVyDQogIHByaW9yaXRpemVkX3RibF9vaV9UdW1vcl8xMCA9IGdldF90b3Bfbl9scl9wYWlycygNCiAgICBtdWx0aW5pY2hlbmV0X291dHB1dCRwcmlvcml0aXphdGlvbl90YWJsZXMsIA0KICAgIDIwLCANCiAgICBncm91cHNfb2kgPSBncm91cF9vaSwgDQogICAgcmVjZWl2ZXJzX29pID0gcmVjZWl2ZXJfb2kNCiAgKSANCiAgDQogICMgQ3JlYXRlIHRoZSBjb21iaW5lZCBwbG90DQogIGNvbWJpbmVkX3Bsb3QgPSBtYWtlX2xpZ2FuZF9hY3Rpdml0eV90YXJnZXRfcGxvdCgNCiAgICBncm91cF9vaSwgDQogICAgcmVjZWl2ZXJfb2ksIA0KICAgIHByaW9yaXRpemVkX3RibF9vaV9UdW1vcl8xMCwNCiAgICBtdWx0aW5pY2hlbmV0X291dHB1dCRwcmlvcml0aXphdGlvbl90YWJsZXMsIA0KICAgIG11bHRpbmljaGVuZXRfb3V0cHV0JGxpZ2FuZF9hY3Rpdml0aWVzX3RhcmdldHNfREVnZW5lcywgY29udHJhc3RfdGJsLCANCiAgICBtdWx0aW5pY2hlbmV0X291dHB1dCRncm91cGluZ190YmwsIA0KICAgIG11bHRpbmljaGVuZXRfb3V0cHV0JGNlbGx0eXBlX2luZm8sIA0KICAgIGxpZ2FuZF90YXJnZXRfbWF0cml4LCANCiAgICBwbG90X2xlZ2VuZCA9IEZBTFNFDQogICkNCg0KICAjIERpc3BsYXkgdGhlIGZpcnN0IHBhcnQgb2YgdGhlIGNvbWJpbmVkIHBsb3QgKG9wdGlvbmFsKQ0KICBwcmludChjb21iaW5lZF9wbG90KQ0KICANCiAgIyBTYXZlIHRoZSBwbG90IHRvIGEgUERGIGZpbGUgd2l0aCB0aGUgcmVjZWl2ZXIncyBuYW1lDQogIGZpbGVfbmFtZSA9IHBhc3RlMCgibXVsdGluaWNoZV9vdXRwdXQvY3RsX2ludC8iLCByZWNlaXZlcl9vaSwgIl9saWdhbmRfdGFyZ2V0X2JhcnMucGRmIikNCiAgZ2dzYXZlKGZpbGVfbmFtZSwgd2lkdGggPSAxOSwgaGVpZ2h0ID0gMTMsIGRwaSA9IDMwMCkNCn0NCmBgYA0KDQoNCiMjIEluIGNhc2Ugd2UgYXJlIGludGVyZXN0ZWQgaW4gc3BlY2lmaWMgbGlnYW5kIGFuZCB3YW50IHRvIGZpbmQgdGhlIGRvd25zdHJlYW0gZ2VuZXMNCmBgYHtyfQ0KZ3JvdXBfb2kgPSAiaW50Ig0KcmVjZWl2ZXJfb2kgPSAiRUMiDQpsaWdhbmRzX29pID0gIlRnZmIxIiAjIGFkZCBoZXJlIHRoZSBsaWdhbmQNCnByaW9yaXRpemVkX3RibF9saWdhbmRzX29pID0gZ2V0X3RvcF9uX2xyX3BhaXJzKA0KICBtdWx0aW5pY2hlbmV0X291dHB1dCRwcmlvcml0aXphdGlvbl90YWJsZXMsIA0KICAxMDAwMCwgDQogIGdyb3Vwc19vaSA9IGdyb3VwX29pLCANCiAgcmVjZWl2ZXJzX29pID0gcmVjZWl2ZXJfb2kNCiAgKSAlPiUgZmlsdGVyKGxpZ2FuZCAlaW4lIGxpZ2FuZHNfb2kpICMgbGlnYW5kcyBzaG91bGQgc3RpbGwgYmUgaW4gdGhlIG91dHB1dCB0YWJsZXMgb2YgY291cnNlDQoNCnByaW9yaXRpemVkX3RibF9saWdhbmRzX29pDQoNCmNvbWJpbmVkX3Bsb3QgPSBtYWtlX2xpZ2FuZF9hY3Rpdml0eV90YXJnZXRfcGxvdCgNCiAgZ3JvdXBfb2ksIA0KICByZWNlaXZlcl9vaSwgDQogIHByaW9yaXRpemVkX3RibF9saWdhbmRzX29pLCANCiAgbXVsdGluaWNoZW5ldF9vdXRwdXQkcHJpb3JpdGl6YXRpb25fdGFibGVzLCANCiAgbXVsdGluaWNoZW5ldF9vdXRwdXQkbGlnYW5kX2FjdGl2aXRpZXNfdGFyZ2V0c19ERWdlbmVzLCANCiAgY29udHJhc3RfdGJsLCANCiAgbXVsdGluaWNoZW5ldF9vdXRwdXQkZ3JvdXBpbmdfdGJsLCANCiAgbXVsdGluaWNoZW5ldF9vdXRwdXQkY2VsbHR5cGVfaW5mbywgDQogIGxpZ2FuZF90YXJnZXRfbWF0cml4LCANCiAgcGxvdF9sZWdlbmQgPSBGQUxTRSkNCmNvbWJpbmVkX3Bsb3QNCmBgYA0KDQoNCiMgV2l0aCBmaWx0ZXJpbmcgb2YgdGFyZ2V0IGdlbmVzIGJhc2VkIG9uIExSLXRhcmdldCBleHByZXNzaW9uIGNvcnJlbGF0aW9uDQpJbiB0aGUgcHJldmlvdXMgcGxvdHMsIHRhcmdldCBnZW5lcyB3ZXJlIHNob3duIHRoYXQgYXJlIHByZWRpY3RlZCBhcyB0YXJnZXQgZ2VuZSBvZiBsaWdhbmRzIGJhc2VkIG9uIHByaW9yIGtub3dsZWRnZS4gSG93ZXZlciwgd2UgY2FuIHVzZSB0aGUgbXVsdGktc2FtcGxlIG5hdHVyZSBvZiB0aGlzIGRhdGEgdG8gZmlsdGVyIHRhcmdldCBnZW5lcyBiYXNlZCBvbiBleHByZXNzaW9uIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIHVwc3RyZWFtIGxpZ2FuZC1yZWNlcHRvciBwYWlyIGFuZCB0aGUgZG93bnN0cmVhbSB0YXJnZXQgZ2VuZS4gV2Ugd2lsbCBmaWx0ZXIgb3V0IGNvcnJlbGF0ZWQgbGlnYW5kLXJlY2VwdG9yIC0tPiB0YXJnZXQgbGlua3MgdGhhdCBib3RoIHNob3cgaGlnaCBleHByZXNzaW9uIGNvcnJlbGF0aW9uIChzcGVhcm1hbiBvciBwZWFyc29uIGNvcnJlbGF0aW9uID4gMC41MCBpbiB0aGlzIGV4YW1wbGUpIGFuZCBoYXZlIHNvbWUgcHJpb3Iga25vd2xlZGdlIHRvIHN1cHBvcnQgdGhlaXIgbGluay4gTm90ZSB0aGF0IHlvdSBjYW4gb25seSBtYWtlIHRoZXNlIHZpc3VhbGl6YXRpb24gaWYgeW91IHJhbiBzdGVwIDcgb2YgdGhlIGNvcmUgTXVsdGlOaWNoZU5ldCBhbmFseXNpcy4NCg0KDQpgYGB7cn0NCmdyb3VwX29pID0gImVuZCINCmZvciAocmVjZWl2ZXJfb2kgaW4gY2VsbF9saXN0KSB7DQogIA0KICAjIEZpbHRlciBhbmQgcHJlcGFyZSB0aGUgZGF0YQ0KICBscl90YXJnZXRfcHJpb3JfY29yX2ZpbHRlcmVkID0gbXVsdGluaWNoZW5ldF9vdXRwdXQkbHJfdGFyZ2V0X3ByaW9yX2NvciAlPiUNCiAgICBpbm5lcl9qb2luKA0KICAgICAgbXVsdGluaWNoZW5ldF9vdXRwdXQkbGlnYW5kX2FjdGl2aXRpZXNfdGFyZ2V0c19ERWdlbmVzJGxpZ2FuZF9hY3Rpdml0aWVzICU+JSANCiAgICAgICAgZGlzdGluY3QobGlnYW5kLCB0YXJnZXQsIGRpcmVjdGlvbl9yZWd1bGF0aW9uLCBjb250cmFzdCkNCiAgICApICU+JSANCiAgICBpbm5lcl9qb2luKGNvbnRyYXN0X3RibCkgJT4lIGZpbHRlcihncm91cCA9PSBncm91cF9vaSwgcmVjZWl2ZXIgPT0gcmVjZWl2ZXJfb2kpDQogIA0KICBscl90YXJnZXRfcHJpb3JfY29yX2ZpbHRlcmVkX3VwID0gbHJfdGFyZ2V0X3ByaW9yX2Nvcl9maWx0ZXJlZCAlPiUgDQogICAgZmlsdGVyKGRpcmVjdGlvbl9yZWd1bGF0aW9uID09ICJ1cCIpICU+JSANCiAgICBmaWx0ZXIoKHJhbmtfb2ZfdGFyZ2V0IDwgdG9wX25fdGFyZ2V0KSAmIChwZWFyc29uID4gMC41MCB8IHNwZWFybWFuID4gMC41MCkpDQogIA0KICBscl90YXJnZXRfcHJpb3JfY29yX2ZpbHRlcmVkX2Rvd24gPSBscl90YXJnZXRfcHJpb3JfY29yX2ZpbHRlcmVkICU+JSANCiAgICBmaWx0ZXIoZGlyZWN0aW9uX3JlZ3VsYXRpb24gPT0gImRvd24iKSAlPiUgDQogICAgZmlsdGVyKChyYW5rX29mX3RhcmdldCA8IHRvcF9uX3RhcmdldCkgJiAocGVhcnNvbiA8IC0wLjUwIHwgc3BlYXJtYW4gPCAtMC41MCkpICMgZG93bnJlZ3VsYXRpb24gLS0gbmVnYXRpdmUgY29ycmVsYXRpb24NCiAgDQogIGxyX3RhcmdldF9wcmlvcl9jb3JfZmlsdGVyZWQgPSBiaW5kX3Jvd3MoDQogICAgbHJfdGFyZ2V0X3ByaW9yX2Nvcl9maWx0ZXJlZF91cCwgDQogICAgbHJfdGFyZ2V0X3ByaW9yX2Nvcl9maWx0ZXJlZF9kb3duKQ0KICANCiAgIyBHZXQgdGhlIHRvcCA1MCBsaWdhbmQtcmVjZXB0b3IgcGFpcnMgZm9yIHRoZSBjdXJyZW50IHJlY2VpdmVyDQogIHByaW9yaXRpemVkX3RibF9vaSA9IGdldF90b3Bfbl9scl9wYWlycygNCiAgICBtdWx0aW5pY2hlbmV0X291dHB1dCRwcmlvcml0aXphdGlvbl90YWJsZXMsIA0KICAgIDUwLCANCiAgICBncm91cHNfb2kgPSBncm91cF9vaSwgDQogICAgcmVjZWl2ZXJzX29pID0gcmVjZWl2ZXJfb2kpDQogICNOb3cgd2Ugd2lsbCB2aXN1YWxpemUgdGhlIHRvcCBjb3JyZWxhdGVkIHRhcmdldCBnZW5lcyBmb3IgdGhlIExSIHBhaXJzIHRoYXQgYXJlIGFsc28gaW4gdGhlIHRvcCA1MCBMUiBwYWlycyBkaXNjcmltaW5hdGluZyB0aGUgZ3JvdXBzIGZyb20gZWFjaCBvdGhlcg0KICAjIENyZWF0ZSB0aGUgY29ycmVsYXRpb24gcGxvdA0KICBscl90YXJnZXRfY29ycmVsYXRpb25fcGxvdCA9IG1ha2VfbHJfdGFyZ2V0X2NvcnJlbGF0aW9uX3Bsb3QoDQogICAgbXVsdGluaWNoZW5ldF9vdXRwdXQkcHJpb3JpdGl6YXRpb25fdGFibGVzLCANCiAgICBwcmlvcml0aXplZF90Ymxfb2ksICANCiAgICBscl90YXJnZXRfcHJpb3JfY29yX2ZpbHRlcmVkLCANCiAgICBtdWx0aW5pY2hlbmV0X291dHB1dCRncm91cGluZ190YmwsIA0KICAgIG11bHRpbmljaGVuZXRfb3V0cHV0JGNlbGx0eXBlX2luZm8sIA0KICAgIHJlY2VpdmVyX29pLA0KICAgIHBsb3RfbGVnZW5kID0gRkFMU0UpDQogIA0KICAjIERpc3BsYXkgdGhlIGNvbWJpbmVkIHBsb3QgKG9wdGlvbmFsKQ0KICBwcmludChscl90YXJnZXRfY29ycmVsYXRpb25fcGxvdCRjb21iaW5lZF9wbG90KQ0KICANCiAgIyBTYXZlIHRoZSBwbG90IHRvIGEgUERGIGZpbGUgd2l0aCB0aGUgcmVjZWl2ZXIncyBuYW1lDQogIGZpbGVfbmFtZSA9IHBhc3RlMCgibXVsdGluaWNoZV9vdXRwdXQvaW50X2VuZC9jb3JyZWxhdGlvbnBsb3QvIiwgcmVjZWl2ZXJfb2ksICJfZW5kX2xpZ2FuZF90YXJnZXRfY29ycmVsYXRpb24ucGRmIikNCiAgZ2dzYXZlKGZpbGVfbmFtZSwgbHJfdGFyZ2V0X2NvcnJlbGF0aW9uX3Bsb3QkY29tYmluZWRfcGxvdCwgd2lkdGggPSAxOSwgaGVpZ2h0ID0gMTMsIGRwaSA9IDMwMCkNCn0NCmBgYA0KDQoNCg0KdmlzdWFsaXplIHRoZSBleHByZXNzaW9uIGNvcnJlbGF0aW9uIGluIHRoZSBmb2xsb3dpbmcgd2F5IGZvciBhIHNlbGVjdGVkIExSIHBhaXIgYW5kIHRoZWlyIHRhcmdldHM6DQoNCmBgYHtyfQ0KbGlnYW5kX29pID0gIlRnZmIxIg0KcmVjZXB0b3Jfb2kgPSAiVGdmYnIzIg0Kc2VuZGVyX29pID0gYygiTW9ubyIsIk1waCIpDQpyZWNlaXZlcl9vaSA9ICJFQyINCg0KbHJfdGFyZ2V0X3NjYXR0ZXJfcGxvdCA9IG1ha2VfbHJfdGFyZ2V0X3NjYXR0ZXJfcGxvdCgNCiAgbXVsdGluaWNoZW5ldF9vdXRwdXQkcHJpb3JpdGl6YXRpb25fdGFibGVzLCANCiAgbGlnYW5kX29pLCByZWNlcHRvcl9vaSwgc2VuZGVyX29pLCByZWNlaXZlcl9vaSwgDQogIG11bHRpbmljaGVuZXRfb3V0cHV0JGNlbGx0eXBlX2luZm8sIA0KICBtdWx0aW5pY2hlbmV0X291dHB1dCRncm91cGluZ190YmwsIA0KICBscl90YXJnZXRfcHJpb3JfY29yX2ZpbHRlcmVkKQ0KDQpscl90YXJnZXRfc2NhdHRlcl9wbG90DQpgYGANCg0KDQoNCiMgTmV4dCBjaGFwdCAsSW50ZXJjZWxsdWxhciByZWd1bGF0b3J5IG5ldHdvcmsgaW5mZXJlbmNlIGFuZCB2aXN1YWxpemF0aW9uDQoNCkluIHRoZSBwbG90cyBiZWZvcmUsIHdlIGRlbW9uc3RyYXRlZCB0aGF0IHNvbWUgREUgZ2VuZXMgaGF2ZSBib3RoIGV4cHJlc3Npb24gY29ycmVsYXRpb24gYW5kIHByaW9yIGtub3dsZWRnZSBzdXBwb3J0IHRvIGJlIGRvd25zdHJlYW0gb2YgbGlnYW5kLXJlY2VwdG9yIHBhaXJzLiBJbnRlcmVzdGluZ2x5LCBzb21lIHRhcmdldCBnZW5lcyBjYW4gYmUgbGlnYW5kcyBvciByZWNlcHRvcnMgdGhlbXNlbHZlcy4gVGhpcyBpbGx1c3RyYXRlcyB0aGF0IGNlbGxzIGNhbiBzZW5kIHNpZ25hbHMgdG8gb3RoZXIgY2VsbHMsIHdobyBhcyBhIHJlc3BvbnNlIHRvIHRoZXNlIHNpZ25hbHMgcHJvZHVjZSBzaWduYWxzIHRoZW1zZWx2ZXMgdG8gZmVlZGJhY2sgdG8gdGhlIG9yaWdpbmFsIHNlbmRlciBjZWxscywgb3Igd2hvIHdpbGwgZWZmZWN0IG90aGVyIGNlbGwgdHlwZXMuDQoNCkFzIGxhc3QgcGxvdCwgd2UgY2FuIGdlbmVyYXRlIGEgJ3N5c3RlbXMnIHZpZXcgb2YgdGhlc2UgaW50ZXJjZWxsdWxhciBmZWVkYmFjayBhbmQgY2FzY2FkZSBwcm9jZXNzZXMgdGhhbiBjYW4gYmUgb2NjdXJpbmcgYmV0d2VlbiB0aGUgZGlmZmVyZW50IGNlbGwgcG9wdWxhdGlvbnMgaW52b2x2ZWQuIEluIHRoaXMgcGxvdCwgd2Ugd2lsbCBkcmF3IGxpbmtzIGJldHdlZW4gbGlnYW5kcyBvZiBzZW5kZXIgY2VsbCB0eXBlcyB0aGVpciBsaWdhbmQvcmVjZXB0b3ItYW5ub3RhdGVkIHRhcmdldCBnZW5lcyBpbiByZWNlaXZlciBjZWxsIHR5cGVzLiBTbyBsaW5rcyBhcmUgIyMjbGlnYW5kLXRhcmdldCBsaW5rcyAoPSBnZW5lIHJlZ3VsYXRvcnkgbGlua3MpIGFuZCBub3QgbGlnYW5kLXJlY2VwdG9yIHByb3RlaW4tcHJvdGVpbiBpbnRlcmFjdGlvbnMjIyMjIyEgV2Ugd2lsbCBpbmZlciB0aGlzIGludGVyY2VsbHVsYXIgcmVndWxhdG9yeSBuZXR3b3JrIGhlcmUgZm9yIHRoZSB0b3A1MCBpbnRlcmFjdGlvbnMuIFlvdSBjYW4gaW5jcmVhc2UgdGhpcyB0byBpbmNsdWRlIG1vcmUgaGl0cyBvZiBjb3Vyc2UgKHJlY29tbWVuZGVkKS4NCg0KYGBge3J9DQpwcmlvcml0aXplZF90Ymxfb2kgPSBnZXRfdG9wX25fbHJfcGFpcnMoDQogIG11bHRpbmljaGVuZXRfb3V0cHV0JHByaW9yaXRpemF0aW9uX3RhYmxlcywgDQogIDE1MCwgDQogIHJhbmtfcGVyX2dyb3VwID0gRkFMU0UpDQoNCmxyX3RhcmdldF9wcmlvcl9jb3JfZmlsdGVyZWQgPSANCiAgbXVsdGluaWNoZW5ldF9vdXRwdXQkcHJpb3JpdGl6YXRpb25fdGFibGVzJGdyb3VwX3ByaW9yaXRpemF0aW9uX3RibCRncm91cCAlPiUgdW5pcXVlKCkgJT4lIA0KICBsYXBwbHkoZnVuY3Rpb24oZ3JvdXBfb2kpew0KICAgIGxyX3RhcmdldF9wcmlvcl9jb3JfZmlsdGVyZWQgPSBtdWx0aW5pY2hlbmV0X291dHB1dCRscl90YXJnZXRfcHJpb3JfY29yICU+JQ0KICAgICAgaW5uZXJfam9pbigNCiAgICAgICAgbXVsdGluaWNoZW5ldF9vdXRwdXQkbGlnYW5kX2FjdGl2aXRpZXNfdGFyZ2V0c19ERWdlbmVzJGxpZ2FuZF9hY3Rpdml0aWVzICU+JQ0KICAgICAgICAgIGRpc3RpbmN0KGxpZ2FuZCwgdGFyZ2V0LCBkaXJlY3Rpb25fcmVndWxhdGlvbiwgY29udHJhc3QpDQogICAgICAgICkgJT4lIA0KICAgICAgaW5uZXJfam9pbihjb250cmFzdF90YmwpICU+JSBmaWx0ZXIoZ3JvdXAgPT0gZ3JvdXBfb2kpDQogICAgDQogICAgbHJfdGFyZ2V0X3ByaW9yX2Nvcl9maWx0ZXJlZF91cCA9IGxyX3RhcmdldF9wcmlvcl9jb3JfZmlsdGVyZWQgJT4lIA0KICAgICAgZmlsdGVyKGRpcmVjdGlvbl9yZWd1bGF0aW9uID09ICJ1cCIpICU+JSANCiAgICAgIGZpbHRlciggKHJhbmtfb2ZfdGFyZ2V0IDwgdG9wX25fdGFyZ2V0KSAmIChwZWFyc29uID4gMC41MCB8IHNwZWFybWFuID4gMC41MCkpDQogICAgDQogICAgbHJfdGFyZ2V0X3ByaW9yX2Nvcl9maWx0ZXJlZF9kb3duID0gbHJfdGFyZ2V0X3ByaW9yX2Nvcl9maWx0ZXJlZCAlPiUgDQogICAgICBmaWx0ZXIoZGlyZWN0aW9uX3JlZ3VsYXRpb24gPT0gImRvd24iKSAlPiUgDQogICAgICBmaWx0ZXIoIChyYW5rX29mX3RhcmdldCA8IHRvcF9uX3RhcmdldCkgJiAocGVhcnNvbiA8IC0wLjUwIHwgc3BlYXJtYW4gPCAtMC41MCkpDQogICAgbHJfdGFyZ2V0X3ByaW9yX2Nvcl9maWx0ZXJlZCA9IGJpbmRfcm93cygNCiAgICAgIGxyX3RhcmdldF9wcmlvcl9jb3JfZmlsdGVyZWRfdXAsIA0KICAgICAgbHJfdGFyZ2V0X3ByaW9yX2Nvcl9maWx0ZXJlZF9kb3duDQogICAgICApDQp9KSAlPiUgYmluZF9yb3dzKCkNCg0KbHJfdGFyZ2V0X2RmID0gbHJfdGFyZ2V0X3ByaW9yX2Nvcl9maWx0ZXJlZCAlPiUgDQogIGRpc3RpbmN0KGdyb3VwLCBzZW5kZXIsIHJlY2VpdmVyLCBsaWdhbmQsIHJlY2VwdG9yLCBpZCwgdGFyZ2V0LCBkaXJlY3Rpb25fcmVndWxhdGlvbikgDQpgYGANCg0KYGBge3J9DQpuZXR3b3JrID0gaW5mZXJfaW50ZXJjZWxsdWxhcl9yZWd1bGF0b3J5X25ldHdvcmsobHJfdGFyZ2V0X2RmLCBwcmlvcml0aXplZF90Ymxfb2kpDQpuZXR3b3JrJGxpbmtzICU+JSBoZWFkKCkNCmBgYA0KDQpgYGB7cn0NCm5ldHdvcmtfZ3JhcGggPSB2aXN1YWxpemVfbmV0d29yayhuZXR3b3JrLCBjb2xvcnNfc2VuZGVyKQ0KbmV0d29ya19ncmFwaCRwbG90DQoNCmdnc2F2ZSgibXVsdGluaWNoZV9vdXRwdXQvbXVsdGljb250cmFzdF9hbGxfY2VsbHMvL291dHB1dC9pbnRlcmNlbGx1bGFyX3JlZ3VsYXRvcnlfbmV0d29yay5wZGYiLCBuZXR3b3JrX2dyYXBoJHBsb3QsIHdpZHRoID0gMjEsIGhlaWdodCA9IDEzLGRwaSA9IDMwMCkNCmBgYA0KDQojIEludGVyZXN0aW5nbHksIHdlIGNhbiBhbHNvIHVzZSB0aGlzIG5ldHdvcmsgdG8gZnVydGhlciBwcmlvcml0aXplIGRpZmZlcmVudGlhbCBDQ0MgaW50ZXJhY3Rpb25zLiBIZXJlIHdlIHdpbGwgYXNzdW1lIHRoYXQgdGhlIG1vc3QgaW1wb3J0YW50IExSIGludGVyYWN0aW9ucyBhcmUgdGhlIG9uZXMgdGhhdCBhcmUgaW52b2x2ZWQgaW4gdGhpcyBpbnRlcmNlbGx1bGFyIHJlZ3VsYXRvcnkgbmV0d29yay4gV2UgY2FuIGdldCB0aGVzZSBpbnRlcmFjdGlvbnMgYXMgZm9sbG93czoNCg0KYGBge3J9DQpuZXR3b3JrJHByaW9yaXRpemVkX2xyX2ludGVyYWN0aW9ucw0KYGBgDQoNCg0KYGBge3J9DQpwcmlvcml0aXplZF90Ymxfb2lfbmV0d29yayA9IHByaW9yaXRpemVkX3RibF9vaSAlPiUgaW5uZXJfam9pbigNCiAgbmV0d29yayRwcmlvcml0aXplZF9scl9pbnRlcmFjdGlvbnMpDQpwcmlvcml0aXplZF90Ymxfb2lfbmV0d29yaw0KYGBgDQpJbnRlcmVzdGluZ2x5LCB3ZSBjYW4gYWxzbyB1c2UgdGhpcyBuZXR3b3JrIHRvIGZ1cnRoZXIgcHJpb3JpdGl6ZSBkaWZmZXJlbnRpYWwgQ0NDIGludGVyYWN0aW9ucy4gSGVyZSB3ZSB3aWxsIGFzc3VtZSB0aGF0IHRoZSBtb3N0IGltcG9ydGFudCBMUiBpbnRlcmFjdGlvbnMgYXJlIHRoZSBvbmVzIHRoYXQgYXJlIGludm9sdmVkIGluIHRoaXMgaW50ZXJjZWxsdWxhciByZWd1bGF0b3J5IG5ldHdvcmsuIFdlIGNhbiBnZXQgdGhlc2UgaW50ZXJhY3Rpb25zIGFzIGZvbGxvd3M6DQoNCg0KYGBge3J9DQpncm91cF9vaSA9ICJlbmQiDQpwcmlvcml0aXplZF90Ymxfb2lfSW50ID0gcHJpb3JpdGl6ZWRfdGJsX29pX25ldHdvcmsgJT4lIGZpbHRlcihncm91cCA9PSBncm91cF9vaSkNCg0KcGxvdF9vaSA9IG1ha2Vfc2FtcGxlX2xyX3Byb2RfYWN0aXZpdHlfcGxvdHNfT21uaXBhdGgoDQogIG11bHRpbmljaGVuZXRfb3V0cHV0JHByaW9yaXRpemF0aW9uX3RhYmxlcywgDQogIHByaW9yaXRpemVkX3RibF9vaV9JbnQgJT4lIGlubmVyX2pvaW4obHJfbmV0d29ya19hbGwpDQogICkNCnBsb3Rfb2kNCg0KZ2dzYXZlKCJtdWx0aW5pY2hlX291dHB1dC9pbnRfZW5kL2ludF9Qcmlvcml0aXplZF9MUl9iYXNlZF9vbl9pbnRyZWNlbGx1bGFyX25ldHdvcmsucGRmIiwgcGxvdF9vaSwgd2lkdGggPSAxNCwgaGVpZ2h0ID0gOCxkcGkgPSAzMDApDQpgYGANCg0K